package com.one.rope.mvp.basecore.aspet;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.one.rope.mvp.basecore.bean.ResponseObject;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * @author Weijian.liu
 * @desc 控制器全局拦截器
 * @date 2019/3/29
 */
@Component
@Aspect
@Slf4j
public class LogMethodInteceptor {

  private static ThreadLocal<Long> startTime = new ThreadLocal<Long>();
  private static ThreadLocal<String> key = new ThreadLocal<String>();
  private static ObjectMapper objectMapper = new ObjectMapper();
  /**
   * 定义拦截规则：拦截有@LogMethod注解的方法
   */
  @Pointcut("@annotation(com.one.rope.mvp.basecore.annotation.LogMethod)")
  public void controllerMethodPointcut() {

  }

  /**
   * 请求方法前打印内容
   * @param joinPoint
   */
  @Before("controllerMethodPointcut()")
  public void doBefore(JoinPoint joinPoint) {
    // 请求开始时间
    startTime.set(System.currentTimeMillis());
    RequestAttributes ra = RequestContextHolder.getRequestAttributes();
    ServletRequestAttributes sra = (ServletRequestAttributes) ra;
    HttpServletRequest request = sra.getRequest();
    // 获取请求头
    Enumeration<String> enumeration = request.getHeaderNames();
    StringBuffer headers = new StringBuffer();
    while (enumeration.hasMoreElements()) {
      String name = enumeration.nextElement();
      String value = request.getHeader(name);
      if("token".equals(name)){
        log.info("request token: {}", value);
      }
      headers.append(name + ":" + value).append(",");
    }
    String uri = request.getRequestURI();
    log.info("request url: {}", uri);
    String method = request.getMethod();
    StringBuffer params = new StringBuffer();
    if (HttpMethod.GET.toString().equals(method)) {// get请求
      String queryString = request.getQueryString();
      if (StringUtils.isNotBlank(queryString)) {
        params.append(queryString);
      }
    } else {//其他请求
      Object[] paramsArray = joinPoint.getArgs();
      if (paramsArray != null && paramsArray.length > 0) {
        for (int i = 0; i < paramsArray.length; i++) {
          if (paramsArray[i] instanceof Serializable) {
            params.append(paramsArray[i].toString()).append(",");
          } else {
            try {
              String param= objectMapper.writeValueAsString(paramsArray[i]);
              if(StringUtils.isNotBlank(param))
                params.append(param).append(",");
            } catch (JsonProcessingException e) {
              log.error("doBefore obj to json handle obj={},msg={}",paramsArray[i],e);
            }
          }
        }
      }
    }
    key.set(uri);
    log.info("request params: {}", params.toString());
  }

  /**
   * 在方法执行后打印返回内容
   * @param obj
   */
  @AfterReturning(returning = "obj", pointcut = "controllerMethodPointcut()")
  public void doAfterReturing(Object obj) {
    long costTime = System.currentTimeMillis() - startTime.get();
    String uri = key.get();
    startTime.remove();
    key.remove();
    ResponseObject responseObject = (ResponseObject)obj;
    responseObject.setUsageTime(costTime);
    log.info("response result==={}", responseObject.toString());
  }
}
